#include "stdafx.h"
#include "List.h"
//////////////////////////////////////////////////////////////////////////

elem* elem_construct()
{
	elem *createdelem = (elem*)calloc(1, sizeof(elem));

	createdelem->next = NULL;
	createdelem->prev = NULL;
	createdelem->data = 0;
	createdelem->freq = 0;
	
	return createdelem;
}

int elem_OK(elem* elemtocheck) {
	if (elemtocheck == NULL) DOUT("#ALERT_NO-OK - Elem_OK has received a null *elem");
	if (elemtocheck->freq < 0) DOUT("#ALERT_NO-OK - Elem_OK detected a negative frequency stat in an element");
	else return true;

	return false;
}

int elem_destruct(elem* ElemToDelete)
{
	if (!elem_OK(ElemToDelete)) return((DOUT("Elem not ok, _destruct outta here!"), -1));
	ElemToDelete->next = NULL;
	ElemToDelete->prev = NULL;
	ElemToDelete->data = POISON;
	free(ElemToDelete);
	return 1;
}

//////////////////////////////////////////////////////////////////////////
/************************************************************************/
/* @note There's an additional element to properly delete empty lists   */
/************************************************************************/
list* list_construct()
{
	list *createdlist = (list*)calloc(1, sizeof(list));
	
	elem *createdlisthead = elem_construct();

	createdlist->head = createdlisthead;
	createdlist->len = 0;

	return createdlist;
}

int list_OK(list* listtocheck)
{
	if (listtocheck == NULL) DOUT("#ALERT_NO-OK - List_OK has received a null *list");
	else if (listtocheck->head == NULL) DOUT("#ALERT_NO-OK - Checked list's headless");
	else if (listtocheck->len < 0) DOUT("#ALERT_NO-OK - Checked list claims to have negative length");
	else return true;

	return false;
}

int list_destruct(list* ListToDelete) 
{
	if (!list_OK(ListToDelete)) return(( DOUT("List not ok, _destruct outta here!"), -1 ));

	for (elem *currelem = ListToDelete->head, *nextelem = currelem->next; nextelem != NULL;
			currelem = nextelem, nextelem = currelem->next) {
		elem_destruct(currelem);
	}
	free(ListToDelete);
	return 1;
}

//////////////////////////////////////////////////////////////////////////

void list_add(list_data InData, list* ListToAddTo) 
{
	assert(("PRE: list_add has received a valid (OK) list", list_OK(ListToAddTo)));
	
	elem* freshelem = elem_construct();
	freshelem->data = InData;

	freshelem->next = ListToAddTo->head;
	freshelem->next->prev = freshelem;
	ListToAddTo->head = freshelem;
	ListToAddTo->len++;

	assert(("POST: list_add has produced a valid (OK) list", list_OK(ListToAddTo)));
}

/************************************************************************/
/* @brief _deleteentry will delete first element if 0 is given and so on*/
/************************************************************************/
void list_deleteentry(int Number, list* ListToRemoveFrom)
{
	assert(("PRE: list_deleteentry has received a valid (OK) list", list_OK(ListToRemoveFrom)));
	if (Number >= ListToRemoveFrom->len) {
		DOUT("list_deleteentry has received an invalid delete-index");
		return;
	}

	elem* currelem = ListToRemoveFrom->head;
	for (int iter = 0; iter < Number; iter++) {
		currelem = currelem->next;
	}

	currelem->prev->next = currelem->next;
	currelem->next->prev = currelem->prev;
	elem_destruct(currelem);
	ListToRemoveFrom->len--;

	assert(("POST: list_deleteentry has produced a valid (OK) list", list_OK(ListToRemoveFrom)));
}

elem* list_find(list_data DataToFind, list* ListToSearchIn)
{
	assert(("PRE: list_find has received a valid (OK) list", list_OK(ListToSearchIn)));

	elem* currelem = ListToSearchIn->head;
	for (; strcmp(currelem->data, DataToFind);
		currelem = currelem->next) {
		if (currelem == NULL) break;
	}

	assert(("POST: list_find has produced a valid (OK) list", list_OK(ListToSearchIn)));
	return currelem;
}

//////////////////////////////////////////////////////////////////////////
